import std;

var RED : Color = (224, 0, 0);
var DARK_BLUE : Color = (0, 0, 128);

var WIDTH = 800;
var HEIGHT = 600;

var s = HiScreen(WIDTH, HEIGHT);

trait Drawable {
    def draw(var self : Self, var win : HiScreen) : Self;
}

record Circle {
    x : Int;
    y : Int;
    r : Int;
    color : Color;
}

implement Drawable for Circle {
    def draw(var self : Self, var win : HiScreen) : HiScreen {}
}

record Rectangle {
    x : Int;
    y : Int;
    width : Int;
    height : Int;
    color : Color;
}

implement Drawable for Rectangle {
    def draw(var self : Self, var win : HiScreen) : HiScreen {}
}

record Ball {
    c : Circle;
    vx : Int;
    vy : Int;
}

var r = Rectangle(500, 100, 200, 100, DARK_BLUE);
var c = Circle(400, 300, 50, RED);
var b = Ball(c, 3, 1);

trait Movable {
    def move(var self : Self) : Unit;
}

implement Movable for Ball {
    def move(var self : Self) : Unit {
        var x = self.c.x;
        var y = self.c.y;
        var r = self.c.r;

        x = x + self.vx;
        y = y + self.vy;

        if (x <= r or x + r >= WIDTH) {
            self.vx = 0 - self.vx;
        }

        if (y <= r or y + r >= HEIGHT) {
            self.vy = 0 - self.vy;
        }

        self.c.x = x;
        self.c.y = y;
    }
}

def clear(var s : HiScreen) : HiScreen {
    s.fill((192, 192, 192));
    return s;
}

def update(var s : HiScreen) : HiScreen {
    b.move();
    var show = clear |> b.c.draw |> r.draw;
    show(s);
}

s.run(update);

